package cn.jhz.learn.community_dynamic.wbms.controller.api;

import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import cn.jhz.learn.community_dynamic.CommunityDynamicApplication;
import cn.jhz.learn.community_dynamic.common.bean.JsonData;
import cn.jhz.learn.community_dynamic.common.exception.RequestException;
import cn.jhz.learn.community_dynamic.dao.PostClassJpaRepository;
import cn.jhz.learn.community_dynamic.dao.PostJpaRepository;
import cn.jhz.learn.community_dynamic.dao.TopicJpaRepository;
import cn.jhz.learn.community_dynamic.dao.UserJpaRepository;
import cn.jhz.learn.community_dynamic.manager.PostManager;
import cn.jhz.learn.community_dynamic.service.PostService;
import cn.jhz.learn.community_dynamic.vo.wbms.PostView;

@RestController
@RequestMapping("api/")
public class AuthPostController {
    private final UserJpaRepository userJpaRepository;
    private final PostJpaRepository postJpaRepository;
    private final PostClassJpaRepository postClassJpaRepository;
    private final TopicJpaRepository topicJpaRepository;
    private final PostManager postManager;
    private final PostService postService;

    static private final List<Byte> allStatus = Arrays.asList((byte) 0, (byte) 1, (byte) 2, (byte) 3);
    static private final List<Byte> allIsOpens = Arrays.asList((byte) 0, (byte) 1);

    @Autowired
    public AuthPostController(PostJpaRepository postJpaRepository, TopicJpaRepository topicJpaRepository,
	    UserJpaRepository userJpaRepository, PostClassJpaRepository postClassJpaRepository, PostManager postManager,
	    PostService postService) {
	super();
	this.postJpaRepository = postJpaRepository;
	this.topicJpaRepository = topicJpaRepository;
	this.postClassJpaRepository = postClassJpaRepository;
	this.userJpaRepository = userJpaRepository;
	this.postManager = postManager;
	this.postService = postService;
    }

    @GetMapping("auth/wbms/post/all")
    @PreAuthorize("hasAuthority('post::get_all')")
    public JsonData getAll(@RequestParam("page") Integer page, @RequestParam("size") Integer size) {
	return JsonData
		.newSuccessInstance(this.postJpaRepository.findAll(PageRequest.of(page - 1, size)).map(PostView::adpt));
    }

    /**
     * TODO 缺少参数合法校验、有效校验
     * 
     * @param topicId
     * @param page
     * @param size
     * @return
     */
    @GetMapping("auth/wbms/post/topic/all")
    @PreAuthorize("hasAuthority('post::get_all_topic')")
    public JsonData getAllPostByClass(@RequestParam("topic_id") Integer topicId, @RequestParam("page") Integer page,
	    @RequestParam("size") Integer size) {

	return JsonData.newSuccessInstance(this.postJpaRepository.findByTopicsAndStatusInAndIsOpenIn(
		this.topicJpaRepository.findById(topicId).orElseThrow(() -> new RequestException("无效主题")), allStatus,
		allIsOpens, PageRequest.of(page - 1, size)).map(PostView::adpt));
    }

    /**
     * TODO 缺少参数合法校验、有效校验
     * 
     * @param classId
     * @param page
     * @param size
     * @return
     */
    @GetMapping("auth/wbms/post/class/all")
    @PreAuthorize("hasAuthority('post::get_all_class')")
    public JsonData getAllPostTopic(@RequestParam("class_id") Integer classId, @RequestParam("page") Integer page,
	    @RequestParam("size") Integer size) {
	return JsonData.newSuccessInstance(this.postJpaRepository.findByPostClassAndStatusInAndIsOpenIn(
		this.postClassJpaRepository.findById(classId).orElseThrow(() -> new RequestException("无效分类")),
		allStatus, allIsOpens, PageRequest.of(page - 1, size)).map(PostView::adpt));
    }

    /**
     * 
     * @param title
     * @param page
     * @param size
     * @return
     */
    @GetMapping("auth/wbms/post/title/all")
    @PreAuthorize("hasAuthority('post::get_all_title')")
    public JsonData getAllPostByTitle(@RequestParam("title") String title, @RequestParam("page") Integer page,
	    @RequestParam("size") Integer size) {

	return JsonData.newSuccessInstance(this.postJpaRepository.findByTitleContainingAndStatusInAndIsOpenIn(title,
		allStatus, allIsOpens, PageRequest.of(page - 1, size)).map(PostView::adpt));
    }

    @GetMapping("auth/wbms/post/user/all")
    @PreAuthorize("hasAuthority('post::get_all_user')")
    public JsonData getAllPostByUser(@RequestParam("user_id") Long id, @RequestParam("page") Integer page,
	    @RequestParam("size") Integer size) {
	return JsonData
		.newSuccessInstance(this.postJpaRepository
			.findByUser(this.userJpaRepository.findByLoginId(id)
				.orElseThrow(() -> new RequestException("无效用户")), PageRequest.of(page - 1, size))
			.map(PostView::adpt));
    }

    @GetMapping("auth/wbms/post/review/all")
    @PreAuthorize("hasAuthority('post::get_all_review')")
    public JsonData getAllToReviewPost(@RequestParam("size") Integer size) {
	return JsonData.newSuccessInstance(this.postService.getReviewCache(CommunityDynamicApplication.REVIEW_CACHE)
		.get().stream().map(this.postJpaRepository::findById).map(Optional::get).map(PostView::adpt).limit(size)
		.collect(Collectors.toList()));
    }

    @GetMapping("auth/wbms/post/{id}")
    @PreAuthorize("hasAuthority('post::get')")
    public JsonData getAllPostById(@PathVariable("id") Integer id) {
	return JsonData.newSuccessInstance(
		PostView.adpt(this.postJpaRepository.findById(id).orElseThrow(() -> new RequestException("无效文章"))));
    }

    @PatchMapping(value = "auth/wbms/post/status", consumes = "application/x-www-form-urlencoded")
    @PreAuthorize("hasAuthority('post::status_patch')")
    public JsonData patchStatus(@RequestParam("id") Integer id, @RequestParam("operate") Byte operate,
	    @RequestParam(value = "review") Boolean review) {
	if (review) {
	    List<Integer> cache = this.postService.getReviewCache(CommunityDynamicApplication.REVIEW_CACHE).get();
	    cache.remove(id);
	    this.postService.putReviewCache(CommunityDynamicApplication.REVIEW_CACHE, cache);
	}

	return JsonData.newSuccessInstance(PostView.adpt(this.postManager.updateInstanceColumn(
		this.postJpaRepository.findById(id).orElseThrow(() -> new RequestException("文章不存在")), operate)));
    }

}
